package com.admin.domain.media;

import com.admin.utils.HaiyinException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.util.NameValue;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.BatchStatus;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * Qiniu上传
 *
 * @className QiniuUploader
 * @author jinyu
 * @date Apr 28, 2017
 * @since JDK 1.8
 * @see
 */
public class QiniuUploader {
    private String domain = "";
    private final String bucket;
    private final UploadManager um;
    private final BucketManager bm;
    private final Auth auth;

    public QiniuUploader(MediaProperties mp) {
        this(mp, new Configuration());
    }

    public QiniuUploader(MediaProperties mp, Configuration configuration) {
        this.domain = mp.getDomain();
        this.bucket = mp.getBucket();
        this.auth = Auth.create(mp.getAccessKey(), mp.getSecretKey());
        this.um = new UploadManager(configuration);
        this.bm = new BucketManager(auth, configuration);
    }

    /**
     * 上传文件
     *
     * @param is
     *            数据流
     * @param mediaId
     *            媒体ID(相当于文件名)，可为空
     * @return name 为 七牛key,value 为 七牛链接(保证domain不为空)
     */
    public NameValue upload(InputStream is, String mediaId) {
        try {
            // 可用prefix + media
            String token = auth.uploadToken(bucket, mediaId);
            Response response = um.put(is, mediaId, token, null, null);
            JSONObject obj = (JSONObject) JSON.parse(response.body());
            String name = obj.getString("key");
            String value = String.format("%s/%s", domain, URLEncoder.encode(name, "utf-8"));
            return new NameValue(name, value);
        } catch (QiniuException e) {
            throw new HaiyinException("qiniu upload fail < " + e.code() + " < " + e.response.error);
        } catch (UnsupportedEncodingException e) {
            throw new HaiyinException(e); // never
        }
    }

    public List<FileInfo> list() {
        // 文件名前缀
        String prefix = "";
        // 每次迭代的长度限制，最大1000，推荐值 1000
        int limit = 1000;
        // 指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
        String delimiter = "";
        // 列举空间文件列表
        BucketManager.FileListIterator fileListIterator = bm.createFileListIterator(bucket, prefix, limit, delimiter);
        List<FileInfo> files = new ArrayList<>();
        while (fileListIterator.hasNext()) {
            // 处理获取的file list结果
            FileInfo[] items = fileListIterator.next();
            for (FileInfo item : items) {
                files.add(item);
            }
        }
        return files;
    }

    public List<BatchStatus> list(String... mediaIds) {
        try {
            BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
            batchOperations.addStatOps(bucket, mediaIds);
            Response response = bm.batch(batchOperations);
            return JSON.parseArray(response.bodyString(), BatchStatus.class);
        } catch (QiniuException e) {
            throw new HaiyinException("qiniu list fail < " + e.code() + " < " + e.response.error);
        }
    }

    public List<BatchStatus> delete(String... mediaIds) {
        try {
            BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
            batchOperations.addDeleteOp(bucket, mediaIds);
            Response response = bm.batch(batchOperations);
            return JSON.parseArray(response.bodyString(), BatchStatus.class);
        } catch (QiniuException e) {
            throw new HaiyinException("qiniu delete fail < " + e.code() + " < " + e.response.error);
        }
    }

    public FileInfo get(String mediaId) {
        try {
            return bm.stat(bucket, mediaId);
        } catch (QiniuException e) {
            throw new HaiyinException("qiniu get fail < " + e.code() + " < " + e.response.error);
        }
    }

    public Response del(String mediaId) {
        try {
            return bm.delete(bucket, mediaId);
        } catch (QiniuException e) {
            throw new HaiyinException("qiniu get fail < " + e.code() + " < " + e.response.error);
        }
    }

    public InputStream open(String mediaId) {
        try {
            return new URL(String.format("%s/%s", domain, mediaId)).openStream();
        } catch (IOException e) {
            throw new MediaNotFoundException("Could not read file: " + mediaId, e);
        }
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }
}
